﻿using System;
using System.IO;
using System.Collections.Generic;
using System.Configuration;
using System.ComponentModel;
using System.Diagnostics;
using System.ServiceProcess;
using Entities = Vision.Core.Entities;
using Components = Vision.Core.Components;

namespace Vision.Server
{
    /// <summary>
    /// 
    /// </summary>
    public partial class VisionProcessor : ServiceBase
    {
        private Components.ActivityQueueListener QueueListener {get; set;}
        
        /// <summary>
        /// 
        /// </summary>
        public VisionProcessor()
        {
            InitializeComponent();
            this.QueueListener = new Components.ActivityQueueListener(ConfigurationManager.AppSettings["VisionQueue"]);
            this.QueueListener.MessageReceived += new Components.ActivityQueueListener.MessageReceivedEventHandler(QueueListener_MessageReceived);
        }
        
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void QueueListener_MessageReceived(object sender, Components.ActivityQueueListener.MessageEventArgs args)
        {
            try{
                Entities.Activities.VisionActivityMessage eaMessage = (Entities.Activities.VisionActivityMessage)args.MessageBody;
                if (eaMessage != null){
                    using (Components.ActivityCatalog activityCatalog = new Components.ActivityCatalog(ConfigurationManager.AppSettings["VisionCatalog"])){
                        Entities.Activities.VisionActivity visionActivity = activityCatalog.GetVisionActivityFromCatalog(eaMessage.ActivityKey);
                        if (visionActivity == null){
                            throw new Exception("Invalid Activity");
                        }

                        //******************************************************************************************************************************************
                        //Activity Execution Block:                                                                        
                        StringWriter consoleWriter = new StringWriter();
                        Console.SetOut(consoleWriter);
                                                
                        activityCatalog.AddActivityHistoryItem(new Entities.Activities.ActivityHistoryItem() {
                            ActivityId = visionActivity.Id,
                            Event = Entities.Activities.ActivityHistoryEvent.Activity_Execution_Started,
                            Data = string.Empty,
                            Date = DateTime.Now
                        }); 
                        try{
                            using (Components.ActivityExecuter activityExecuter = new Components.ActivityExecuter()){                                
                                activityExecuter.ExecuteVisionActivity(visionActivity, eaMessage.ActivityParams);                                
                            }
                        }
                        catch (Exception ex){                            
                            activityCatalog.AddActivityHistoryItem(new Entities.Activities.ActivityHistoryItem(){
                                ActivityId = visionActivity.Id,
                                Event = Entities.Activities.ActivityHistoryEvent.Activity_Execution_Error,
                                Data = ex.ToString(),
                                Date = DateTime.Now
                            }); 
                        }
                        finally{
                            Console.Out.Flush();                            
                            
                            activityCatalog.AddActivityHistoryItem(new Entities.Activities.ActivityHistoryItem(){
                                ActivityId = visionActivity.Id,
                                Event = Entities.Activities.ActivityHistoryEvent.Activity_Execution_Complete,
                                Data = string.Empty,
                                Date = DateTime.Now
                            });

                            activityCatalog.AddActivityHistoryItem(new Entities.Activities.ActivityHistoryItem(){
                                ActivityId = visionActivity.Id,
                                Event = Entities.Activities.ActivityHistoryEvent.Activity_Execution_Stack,
                                Data = consoleWriter.ToString(),
                                Date = DateTime.Now
                            });                                                        
                        }
                        //******************************************************************************************************************************************                        
                    }
                }                    
            }
            catch (Exception ex){
                EventLog.WriteEntry(ex.ToString(), EventLogEntryType.Error);
            }
        }

         /// <summary>
        /// 
        /// </summary>
        /// <param name="args"></param>
        protected override void OnStart(string[] args)
        {            
            this.QueueListener.Start();
            EventLog.WriteEntry("Vision Service Started", EventLogEntryType.Information);
        }

        /// <summary>
        /// 
        /// </summary>
        protected override void OnStop()
        {
            this.QueueListener.Stop();
            EventLog.WriteEntry("Vision Service Stopped", EventLogEntryType.Information);
        }
                
        /// <summary>
        /// 
        /// </summary>
        static void Main()
        {
            ServiceBase[] ServicesToRun;
            ServicesToRun = new ServiceBase[] { new VisionProcessor() };
            ServiceBase.Run(ServicesToRun);
        }
    }
}
